#include "MainProgram.h"
void printHelp()
{
  printf("Usage: MainProgram [options] [fileName]\n"
	 "options:\n"
	 "-t train : train the svm\n"
	 "-c classification : predict the file is violent video or out\n"
	 );
}
void parseCommandLine(int argc, char ** argv, CommandType &_commandObject)
{
  if( argc != 3 && argc != 2 )
    {
      printHelp() ;
      ERROR("paraments format is wrong!") ;
      exit(-1) ;
    }
  INFO2("program",argv[0]) ;
  INFO2("options",argv[1]) ;
  if( argc == 3 ) INFO2("aviFile",argv[2]) ;

  _commandObject.commandValue = -1 ; 
  if( strcmp(argv[1],"-t") == 0 && argc == 2 ) 
    {
      _commandObject.commandValue = _TRAIN ;
    }
  if( strcmp(argv[1],"-c") == 0 && argc == 3 ) 
    {
      _commandObject.commandValue = _CLASSIFICATION ;
      _commandObject.fileName = std::string(argv[2]) ;
    }
  if( _commandObject.commandValue == (unsigned)(-1) ) 
    {
      printHelp() ;
      ERROR("Options is Unknowed!") ;
      exit(-1) ;
    }
}
void getFileFromPath(const char * _path , std::vector<std::string>& _fileVector)
{
  DIR * pDir ;
  struct dirent * pDirent ;
  _fileVector.clear() ;
  if( _path == NULL )
    {
      ERROR("file path is NULL!") ;
      exit(-1) ;
    }
  pDir = opendir(_path) ;
  while( (pDirent = readdir(pDir)) != NULL )
    {
      if( !(pDirent->d_type & DT_DIR) )
	{
	  INFO2("file name",pDirent->d_name) ;
	  _fileVector.push_back(std::string(pDirent->d_name)) ;
	}
    }
  closedir(pDir) ;
}
bool sceneUnstrand(const char * _videoFileName, const char * _sceneKmeansModel, const char * _sceneSvmModel)
{
  assert(_videoFileName!=NULL&&_sceneKmeansModel!=NULL&&_sceneSvmModel!=NULL) ;
  CvCapture * capture = cvCaptureFromFile(_videoFileName) ;
  if( capture == NULL )
    {
      INFO2("video file name",_videoFileName) ;
      ERROR("can't open the video!") ;
      exit(-1) ;
    }
  
  sceneKmeansModel scenekmeans ;
  scenekmeans.loadKmeansModel(_sceneKmeansModel ) ;
  // 判断
  std::string featureFile = RECOGNITIVE_SCENE_TEMP_PATH + "sift.feature" ;
  std::string histogramFile = RECOGNITIVE_SCENE_TEMP_PATH + "sift.histogram" ;
  std::string imageFile = RECOGNITIVE_SCENE_TEMP_PATH + "tmp.pgm" ;
  SVMClassify svmClassifyModel(_sceneSvmModel) ;
  int imageNum = 1 ;
  IplImage * imagePtr ;
  int sum = 0 ;
  int reg = 0 ;
  while( (imagePtr = cvQueryFrame(capture)) != NULL )
    {
      if( imageNum++ % 30 )
        continue ;
      IplImage * grayImage = NULL ;
      if( imagePtr->nChannels == 3 )
        {
          grayImage = cvCreateImage(cvGetSize(imagePtr),IPL_DEPTH_8U,1) ;
          cvCvtColor(imagePtr,grayImage,CV_BGR2GRAY) ; 
          cvSaveImage(imageFile.c_str(),grayImage) ;
        }
      else
        cvSaveImage(imageFile.c_str(),imagePtr) ;
      std::string command("../SIFT/sift <") ;
      command += imageFile + " >" + featureFile;
      INFO2("sift command",command) ;
      system(command.c_str()) ;
      scenekmeans.getHistogramBykmeans(featureFile.c_str(),histogramFile.c_str()) ;
      svmClassifyModel.classify(histogramFile.c_str()) ;
      if( svmClassifyModel.getClassify() )
        ++ reg ;
      ++ sum ;
    }
  INFO2("reg",reg) ;
  INFO2("sum",sum) ;
  return (reg > (sum>>1)) ;
}
// 计算路径下的所有视频的特征
void calculateFeatureOfPath(const char * _videoPath, const char * _stipPath, const char * _hogFeaturePath, const char * _flowFeaturePath ,const char * _mEIFeaturePath, const char * _featurePath)
{
  if( _videoPath == NULL || _stipPath == NULL || _featurePath == NULL )
    {
      ERROR("path can't be NULL!") ;
      exit(-1) ;
    }
  std::vector<std::string> fileVector ;
  getFileFromPath(_videoPath,fileVector) ;
  
   for( std::vector<std::string>::iterator iter = fileVector.begin() ; iter != fileVector.end() ; ++ iter )
    {
      INFO2("fileName",*iter) ;
      std::string preffix = *iter ;
      std::string::size_type pos = preffix.find('.') ;
      if( pos != std::string::npos )
        preffix.erase(pos) ;
      else
        continue ;
      std::string videoFileName = std::string(_videoPath) + *iter ; // get the absolute path ;
      std::string stipFileName = std::string(_stipPath) + preffix + ".stip" ; // get stip file's absolute path ;
      std::string hogFileName = std::string(_hogFeaturePath) + preffix + ".hog" ;
      std::string flowFileName = std::string(_flowFeaturePath) + preffix + ".hof" ;
      std::string mEIFileName = std::string(_mEIFeaturePath) + preffix + ".mei" ;
      std::string featuresFileName = std::string(_featurePath) + preffix + ".features" ; // get feature's absolute

      INFO2("video file name",videoFileName) ;
      INFO2("stipFileName",stipFileName) ;
      INFO2("hogFileName",hogFileName) ;
      INFO2("flowFileName",flowFileName) ;
      INFO2("featuresFileName",featuresFileName) ;
      INFO2("Motion Enegry Image",mEIFileName) ;

      //MotionEnegry featureMEI(videoFileName.c_str(),mEIFileName.c_str()) ;

      Features featuresObject(videoFileName.c_str(),stipFileName.c_str(),hogFileName.c_str(), flowFileName.c_str(),mEIFileName.c_str(), featuresFileName.c_str()) ;
      featuresObject.getFeaturesFromVideo() ;
    }
}
void trainSvmModel(CommandType &_commandObject) 
{
  INFO1("train svmModel") ;
  // 计算特征
  calculateFeatureOfPath(POSITIVE_PATH.c_str(),POSITIVE_STIP_PATH.c_str(),POSITIVE_HOG_FEATURES_PATH.c_str(),POSITIVE_FLOW_FEATURES_PATH.c_str(),POSITIVE_MEI_FEATURES_PATH.c_str(),POSITIVE_ALL_FEATURES_PATH.c_str()) ;
  INFO1("***********positive features is finished!*************") ;
  calculateFeatureOfPath(NEGETIVE_PATH.c_str(),NEGETIVE_STIP_PATH.c_str(),NEGETIVE_HOG_FEATURES_PATH.c_str(),NEGETIVE_FLOW_FEATURES_PATH.c_str(),NEGETIVE_MEI_FEATURES_PATH.c_str(),NEGETIVE_ALL_FEATURES_PATH.c_str()) ;
  INFO1("***********negetive features is finished!*************") ;
  kmeansCluster kmeans;
  if( access(KMEANS_MODEL_FILE.c_str(),F_OK) != 0 ) 
    {
      kmeans.trainKmeans(POSITIVE_ALL_FEATURES_PATH.c_str(),NEGETIVE_ALL_FEATURES_PATH.c_str(),100,150,KMEANS_MODEL_FILE.c_str()) ;
    }
  else
    kmeans.loadKmeansModel(KMEANS_MODEL_FILE.c_str()) ;
  return ;
  kmeans.getHistogramFromPath(POSITIVE_ALL_FEATURES_PATH.c_str(),POSITIVE_HISTOGRAM_PATH.c_str()) ;
  kmeans.getHistogramFromPath(NEGETIVE_ALL_FEATURES_PATH.c_str(),NEGETIVE_HISTOGRAM_PATH.c_str()) ;
  // 训练模型
  SVMTrain svmModel(SVM_MODEL_FILE.c_str(),SVM_CONFIGURE_FILE.c_str(),POSITIVE_HISTOGRAM_PATH.c_str(),NEGETIVE_HISTOGRAM_PATH.c_str()) ;
  svmModel.trainSvmModel() ;
  /*
  //*****************************scene***************************
  INFO1("*********************scene train**************************");
  siftFeature siftPositiveObject(POSITIVE_SCENE_IMAGE.c_str(),POSITIVE_SCENE_SIFT_FEATURE_PATH.c_str()) ;
  siftFeature siftNegetiveObject(NEGETIVE_SCENE_IMAGE.c_str(),NEGETIVE_SCENE_SIFT_FEATURE_PATH.c_str()) ;
  sceneKmeansModel sceneKmeansModelObject ;
  sceneKmeansModelObject.trainKmeans(POSITIVE_SCENE_SIFT_FEATURE_PATH.c_str(),NEGETIVE_SCENE_SIFT_FEATURE_PATH.c_str(),500,3000,SCENE_KMEANS_MODEL.c_str()) ;
  sceneKmeansModelObject.getHistogramFromPath(POSITIVE_SCENE_SIFT_FEATURE_PATH.c_str(),POSITIVE_SCENE_HISTOGRAM_PATH.c_str()) ;
  sceneKmeansModelObject.getHistogramFromPath(NEGETIVE_SCENE_SIFT_FEATURE_PATH.c_str(),NEGETIVE_SCENE_HISTOGRAM_PATH.c_str()) ;
  INFO1("**********************histogram over************************") ;
  SVMTrain sceneModel(SCENE_SVM_MODEL.c_str(),SVM_CONFIGURE_FILE.c_str(),POSITIVE_SCENE_HISTOGRAM_PATH.c_str(),NEGETIVE_SCENE_HISTOGRAM_PATH.c_str()) ;
  sceneModel.trainSvmModel() ;
  INFO1("******************scene train finish*************************") ;
  */
}
void recognitionVideo(CommandType &_commandObject)
{
  std::string preffix = _commandObject.fileName ;
  std::string::size_type pos = preffix.find('.') ;
  if( pos != std::string::npos )
    preffix.erase(pos) ;
  else
    {
      ERROR("put int video name is wrong") ;
      return ; 
    }
  INFO2("preffix video file",preffix) ;
  std::string videoFileName = RECOGNITIVE_PATH + _commandObject.fileName ; // get the absolute path ;
  std::string stipFileName = RECOGNITIVE_STIP_PATH + preffix + ".stip" ; // get stip file's absolute path ;
  std::string hogFeaturesFileName = RECOGNITIVE_HOG_FEATURES_PATH + preffix + ".hog" ;
  std::string flowFeaturesFileName = RECOGNITIVE_FLOW_FEATURES_PATH + preffix + ".hof" ;
  std::string mEIFeaturesFileName = RECOGNITIVE_MEI_FEATURES_PATH + preffix + ".mei" ;
  std::string allFeaturesFileName = RECOGNITIVE_ALL_FEATURES_PATH + preffix + ".feature" ;
  std::string histogramFeatureFileName = RECOGNITIVE_HISTOGRAM_PATH + preffix + ".histogram" ;
  std::string svmModelFileName = SVM_MODEL_FILE ;
  std::string svmModelConfigure = SVM_CONFIGURE_FILE ;
  std::string recognitionResultFile = RECOGNITIVE_RESULT_PATH + preffix + ".ret" ;
  INFO2("recognition video",videoFileName) ;
  INFO2("stip file",stipFileName) ;
  INFO2("hog file", hogFeaturesFileName) ;
  INFO2("flow file", flowFeaturesFileName) ;
  INFO2("Motion Enegry Image",mEIFeaturesFileName) ;
  INFO2("allFeatureFileName",allFeaturesFileName) ;
  INFO2("histogramFeatureFileName",histogramFeatureFileName) ;
  INFO2("svmModelFileName",svmModelFileName) ;
  INFO2("svmModelConfigure",svmModelConfigure) ;
  // 计算视频特征

  INFO1("***********calculate MEI feature *****************") ;
  //  MotionEnegry featureMEI(videoFileName.c_str(),mEIFeaturesFileName.c_str()) ;
  //  INFO1("***********calculate MEI feature finished***********") ;
  Features featuresObject(videoFileName.c_str(),stipFileName.c_str(),hogFeaturesFileName.c_str(), flowFeaturesFileName.c_str(),mEIFeaturesFileName.c_str(), allFeaturesFileName.c_str()) ;
  featuresObject.getFeaturesFromVideo() ;
  INFO1("***********calculate feature finished***********") ;
  kmeansCluster kmeans ;
  kmeans.loadKmeansModel(KMEANS_MODEL_FILE.c_str()) ;
  kmeans.getHistogramBykmeans(allFeaturesFileName.c_str(),histogramFeatureFileName.c_str()) ;
  // 判断
  SVMClassify svmClassifyModel(svmModelFileName.c_str());
  svmClassifyModel.classify(histogramFeatureFileName.c_str(),recognitionResultFile.c_str()) ;
  INFO1("***********clssify finished**********") ;
  if( svmClassifyModel.getClassify() ) 
    INFO2("violent video",videoFileName) ;
  else
    INFO2("normal video",videoFileName) ;
  /*
  INFO1("***********do scene unstand*******************") ;
  bool sceneFlag = sceneUnstrand(videoFileName.c_str(),SCENE_KMEANS_MODEL.c_str(), SCENE_SVM_MODEL.c_str()) ;
  if( sceneFlag ) 
    INFO2("scene:Boxing",videoFileName);
  else INFO2("scene:normal",videoFileName) ;
  */
  // 综合判断及可视化
  //visualVideo videoDisplay(videoFileName.c_str(),recognitionResultFile.c_str()) ;
}
int main(int argc, char ** argv)
{
  CommandType commandObject ;
  parseCommandLine(argc,argv,commandObject) ;
  switch(commandObject.commandValue)
    {
    case _TRAIN:
      {
	trainSvmModel(commandObject) ;
	break ;
      }
    case _CLASSIFICATION:
      {
	recognitionVideo(commandObject) ;
	break ;
      }
    }
  return 0 ;
}
